<?php
/**
 * Author: Adam
 * Create at 2018/10/7.
 */

namespace App\Utils;

use App\Exceptions\WrongException;
use Illuminate\Support\Facades\Validator;

class ValidatorExtend
{

    public static function render()
    {
        $validateExtend = new ValidatorExtend();

        //拓展手机号码验证
        Validator::extend('str_date', function ($attribute, $value, $parameters) {
            return preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/', $value);
        });
        Validator::extend('mobile', function ($attribute, $value, $parameters) {
            return preg_match('/^1[345789][0-9]{9}$/', $value);
        });

        //拓展密码验证（8-16位字母或者数字）
        Validator::extend('password', function ($attribute, $value, $parameters) {
            return preg_match('/[0-9A-Za-z]{8,16}/', $value);
        });

        //拓展密码验证（6位数字）
        Validator::extend('vcode', function ($attribute, $value, $parameters) {
            return preg_match('/[0-9]{6}/', $value);
        });

        //拓展银行卡验证
        Validator::extend('bankcard', function ($attribute, $value, $parameters) use ($validateExtend) {
            return $validateExtend->checkBankCard($value);
        });

        //拓展身份证验证
        Validator::extend('idcard', function ($attribute, $value, $parameters) use ($validateExtend) {
            return $validateExtend->checkIdcard($value);
        });
    }

    /**
     * 银行卡校验规则
     * @param $cardNumber
     * @return bool
     * @author Adam
     * @date 2018/10/11 9:26
     */
    public function checkBankCard($cardNumber)
    {
        if(preg_match('/[^0-9]{1,}/', $cardNumber)){
            return false;
        }

        $arr_no = str_split($cardNumber);
        $last_n = $arr_no[count($arr_no) - 1];
        krsort($arr_no);
        $i = 1;
        $total = 0;
        foreach ($arr_no as $n) {
            if ($i % 2 == 0) {
                $ix = $n * 2;
                if ($ix >= 10) {
                    $nx = 1 + ($ix % 10);
                    $total += $nx;
                } else {
                    $total += $ix;
                }
            } else {
                $total += $n;
            }
            $i++;
        }
        $total -= $last_n;
        $x = 10 - ($total % 10);
        if ($x == $last_n) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 身份证校验规则
     * @param $idcard
     * @return bool
     * @author Adam
     * @date 2018/10/11 10:35
     */
    public function checkIdcard($idcard)
    {
        $idcard = strtoupper($idcard);
        $regx = "/(^\d{15}$)|(^\d{17}([0-9]|X)$)/";
        $arr_split = array();
        if (!preg_match($regx, $idcard)) {
            return FALSE;
        }
        if (15 == strlen($idcard)) //检查15位
        {
            $regx = "/^(\d{6})+(\d{2})+(\d{2})+(\d{2})+(\d{3})$/";

            @preg_match($regx, $idcard, $arr_split);
            //检查生日日期是否正确
            $dtm_birth = "19" . $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4];
            if (!strtotime($dtm_birth)) {
                return FALSE;
            } else {
                return TRUE;
            }
        } else      //检查18位
        {
            $regx = "/^(\d{6})+(\d{4})+(\d{2})+(\d{2})+(\d{3})([0-9]|X)$/";
            @preg_match($regx, $idcard, $arr_split);
            $dtm_birth = $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4];
            if (!strtotime($dtm_birth)) //检查生日日期是否正确
            {
                return FALSE;
            } else {
                //检验18位身份证的校验码是否正确。
                //校验位按照ISO 7064:1983.MOD 11-2的规定生成，X可以认为是数字10。
                $arr_int = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
                $arr_ch = array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
                $sign = 0;
                for ($i = 0; $i < 17; $i++) {
                    $b = (int)$idcard{$i};
                    $w = $arr_int[$i];
                    $sign += $b * $w;
                }
                $n = $sign % 11;
                $val_num = $arr_ch[$n];
                if ($val_num != substr($idcard, 17, 1)) {
                    return FALSE;
                } //phpfensi.com
                else {
                    return TRUE;
                }
            }
        }

    }

    /**
     * 信息校验
     * @param array $data
     * @param array $rules
     * @param array $messages
     * @return bool
     * @throws WrongException
     * @author Adam
     * @date 2018/10/8 10:39
     */
    public static function validate(array $data, array $rules, array $messages)
    {
        $validator = Validator::make($data, $rules, $messages);
        if ($validator->fails()) {  //判断验证是否失败
            throw new WrongException($validator->errors()->first());
        }
        return true;
    }
}
